import {GameObject} from './GameObject.js';
import {Cell} from './Cell.js';

// 定义 Snake 类，继承自 GameObject 类，用于表示游戏中的蛇
export class Snake extends GameObject{
    // 构造函数，初始化蛇的各种属性
    constructor(info,gamemap){
        // 调用父类的构造函数
        super();
        // 蛇的唯一标识符
        this.id=info.id;
        // 蛇的颜色
        this.color=info.color;
        // 蛇所在的游戏地图
        this.gamemap=gamemap;

        // 存放蛇身的数组，cells[0] 是蛇头
        this.cells=[new Cell(info.r,info.c)];

        // 下一步要走到的位置
        this.next_cell=null;

        // 蛇的移动速度
        this.speed=5;

        // 蛇的移动方向，0: 上，1: 右，2: 下，3: 左
        this.direction=-1;
        // 蛇的状态，idle: 闲置，move: 移动，dead: 死亡
        this.status="idle";

        // 行的偏移量，对应上、右、下、左四个方向
        this.dr=[-1,0,1,0];
        // 列的偏移量，对应上、右、下、左四个方向
        this.dc=[0,1,0,-1];

        // 记录游戏的回合数
        this.step=0;

        // 误差值，用于判断是否到达目的地
        this.eps=1e-2;

        // 蛇眼睛的方向
        this.eye_direction = 0;
        // 左下角的蛇初始朝上，右上角的蛇朝下
        if (this.id === 1) this.eye_direction = 2;  
        // 眼睛的 x 偏移量，对应四个方向
        this.eye_dx=[ 
            [-1,1],
            [1,1],
            [1,-1],
            [-1,-1]
        ];
        // 眼睛的 y 偏移量，对应四个方向
        this.eye_dy=[ 
            [-1,-1],
            [-1,1],
            [1,1],
            [-1,1]
        ];
    }

    // 游戏开始时执行的函数，这里暂时为空
    start(){

    }

    // 设置蛇的移动方向
    set_direction(d){
        this.direction=d;
    }

    // 判断蛇尾是否会前进
    check_tail_increasing(){
        // 前 10 步蛇尾都会前进
        if(this.step<=10) return true;
        // 每 3 步中的第 1 步蛇尾会前进
        if(this.step%3===1)return true;
        return false;
    }

    // 将蛇的状态变成走下一步
    next_step(){
        // 获取当前蛇的移动方向
        const d=this.direction;
        // 计算下一步要走到的位置
        this.next_cell=new Cell(this.cells[0].r+this.dr[d],this.cells[0].c+this.dc[d]);
        // 更新蛇眼睛的方向
        this.eye_direction = d;
        // 重置方向为 -1
        this.direction=-1;
        // 将蛇的状态设置为移动
        this.status="move";
        // 回合数加 1
        this.step++;

        // 获取蛇身的长度
        const k=this.cells.length;
        // 将蛇身每个位置向后移动一位
        for(let i=k;i>0;i--){
            this.cells[i]=JSON.parse(JSON.stringify(this.cells[i-1]));
        }

        // // 检查下一步是否合法
        // if(!this.gamemap.check_valid(this.next_cell)){
        //     // 下一步不合法，将蛇的状态设置为死亡
        //     this.status="die";
        // }
    }

    // 更新蛇的移动状态
    update_move(){
        // 计算蛇头到下一步位置的 x 方向偏移量
        const dx=this.next_cell.x-this.cells[0].x;
        // 计算蛇头到下一步位置的 y 方向偏移量
        const dy=this.next_cell.y-this.cells[0].y;
        // 计算蛇头到下一步位置的距离
        const distance=Math.sqrt(dx*dx+dy*dy);

        // 如果距离小于误差值，说明到达目的地
        if(distance<this.eps){
            // 将下一步位置设置为新的蛇头
            this.cells[0]=this.next_cell;
            // 重置下一步位置为 null
            this.next_cell=null;
            // 将蛇的状态设置为闲置
            this.status="idle";

            // 判断蛇尾是否不增加
            if(!this.check_tail_increasing()){
                // 删除蛇尾
                this.cells.pop();
            }
        }else{
            // 计算本次移动的距离
            const move_distance=this.speed*this.timedelta/1000;
            // 更新蛇头的 x 坐标
            this.cells[0].x+=move_distance*dx/distance;
            // 更新蛇头的 y 坐标
            this.cells[0].y+=move_distance*dy/distance;
            // 判断蛇尾是否不增加
            if(!this.check_tail_increasing()){
                // 获取蛇身的长度
                const k=this.cells.length;
                // 获取蛇尾
                const tail=this.cells[k-1];
                // 获取蛇尾前一个位置
                const tail_target=this.cells[k-2];
                // 计算蛇尾到前一个位置的 x 方向偏移量
                const tail_dx=tail_target.x-tail.x;
                // 计算蛇尾到前一个位置的 y 方向偏移量
                const tail_dy=tail_target.y-tail.y;
                // 更新蛇尾的 x 坐标
                tail.x+=move_distance*tail_dx/distance;
                // 更新蛇尾的 y 坐标
                tail.y+=move_distance*tail_dy/distance;
            }
        }
    }

    // 更新蛇的状态
    update(){
        // 如果蛇的状态是移动
        if(this.status==="move"){
            // 更新蛇的移动状态
            this.update_move();
        }
        // 渲染蛇
        this.render();
    }

    // 渲染蛇
    render() {
        // 获取游戏地图每个格子的边长
        const L = this.gamemap.L;
        // 获取画布的上下文
        const ctx = this.gamemap.ctx;

        // 设置填充颜色为蛇的颜色
        ctx.fillStyle = this.color;

        // 如果蛇的状态是死亡，将填充颜色设置为白色
        if (this.status === "die") {
            ctx.fillStyle = "white";
        }

        // 如果蛇的状态是死亡，将填充颜色设置为白色
        if (this.status === "die") {
            ctx.fillStyle = "white";
        }

        // 遍历蛇身的每个格子
        for (const cell of this.cells) {
            // 开始绘制路径
            ctx.beginPath();
            // 绘制圆形表示蛇身的格子
            ctx.arc(cell.x * L, cell.y * L, L / 2 * 0.8, 0, Math.PI * 2);
            // 填充圆形
            ctx.fill();
        }

        // 遍历蛇身，绘制相邻格子之间的连接部分
        for (let i = 1; i < this.cells.length; i ++ ) {
            const a = this.cells[i - 1], b = this.cells[i];
            // 如果相邻格子的位置非常接近，跳过
            if (Math.abs(a.x - b.x) < this.eps && Math.abs(a.y - b.y) < this.eps)
                continue;
            // 如果相邻格子在同一列
            if (Math.abs(a.x - b.x) < this.eps) {
                // 绘制矩形连接相邻格子
                ctx.fillRect((a.x - 0.4) * L, Math.min(a.y, b.y) * L, L * 0.8, Math.abs(a.y - b.y) * L);
            } else {
                // 绘制矩形连接相邻格子
                ctx.fillRect(Math.min(a.x, b.x) * L, (a.y - 0.4) * L, Math.abs(a.x - b.x) * L, L * 0.8);
            }
        }

        // 设置填充颜色为黑色，用于绘制蛇的眼睛
        ctx.fillStyle = "black";
        // 绘制蛇的两只眼睛
        for(let i=0;i<2;i++){
            // 计算眼睛的 x 坐标
            const eye_x = (this.cells[0].x + this.eye_dx[this.eye_direction][i] * 0.15) * L;
            // 计算眼睛的 y 坐标
            const eye_y = (this.cells[0].y + this.eye_dy[this.eye_direction][i] * 0.15) * L;

            // 开始绘制路径
            ctx.beginPath();
            // 绘制圆形表示眼睛
            ctx.arc(eye_x, eye_y, L * 0.05, 0, Math.PI * 2);
            // 填充圆形
            ctx.fill();
        }
    }
}